home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
RTF
/
textrect.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
6KB
|
286 lines
/* $Header: /usr/people/pcd/Src/RTF/RCS/textrect.C,v 1.1 92/11/23 12:58:56 pcd Exp Locker: pcd $
*/
#include "textrect.h"
#include <stdlib.h>
#include <assert.h>
extern int debug_format = 0;
#include "debug.h"
TextRect::TextRect()
{
lines = 0;
}
TextPosition
TextRect::format(const TextFlow* flow, TextPosition first, TextPosition last,
const BRect& available)
{
if(flow == 0) return first; //@# need this?
bounds_ = available;
LRBox* l = lines;
Extent used;
while(first < last){
Extent margins;
TextPosition local=first;
flow->leaf(first, local)->line_shape(local, margins);//@# optimize this
if(margins.current_x() + margins.right() < bounds().width()
&& margins.top() < bounds().height()){
Extent avail(bounds().left(),
bounds().left() + margins.left(),
bounds().right() - margins.right(),
bounds().top() + margins.top(),
bounds().bottom());
l = new LRBox(l);
first = l->format(flow, first, last, avail, used,
margins.x0); //justification
if(used.bad()){
l = l->destroy();
break;
}
}else
break;
bounds_.inc_top(margins.top() + used.height());
#if SPACE_AFTER /*@@BUG*/
flow->line_shape(first, margins);
#endif
bounds_.inc_top(margins.bottom());
}
lines = l;
return first;
}
void
TextRect::render(const BRect& bounds)
{
LRBox* l = lines;
while(l && l->top() > bounds.bottom())
l = l->prev();
while(l && l->bottom() > bounds.top()){
l->render(bounds);
l = l->prev();
}
}
TextPosition
TextRect::position(Coord x, Coord y)
{
LRBox* l;
for(l = lines; l; l = l->prev())
if(y > l->top())
return l->position(x);
else if(l->prev() == 0)
return l->position(0);
}
Coord
TextRect::locate(TextPosition here, Coord *top, Coord* bottom) const
{
LRBox* l;
for(l = lines; l; l = l->prev())
if(here >= l->first()){
if(top) *top = l->top();
if(bottom) *bottom = l->bottom();
return l->locate(here);
}
if(top) *top = 0;
if(bottom) *bottom = 0;
return -1;
}
/****** Box ******/
Box::Box(Box* prev)
{
prev_ = prev;
formnode = 0;
bytes = 0;
f = first_ = -1;
}
TextPosition
Box::format(const TextFlow* flow, TextPosition first, TextPosition last,
Extent avail, Extent& used, int word_wrap)
{
f = first_ = first;
formnode = flow->leaf(first, first_);
if(formnode){
Qty q = last - first;
if(q > formnode->bytes() - first_)
q = formnode->bytes() - first_;
Debug(format, ("formatting: [%.*s]\n", q, formnode->data()+first_));
if(bytes = formnode->character_shape(first_, q,
avail, used, word_wrap)){
Debug(format, ("%d bytes formatted.\n", bytes));
return first + bytes;
}
}
Debug(format, ("won't fit at %d.\n", avail.current_x()));
used.make_bad();
return first;
}
void
Box::y(Coord yy) //@# should be an LRBox member
{
Box* bx;
for(bx = this; bx; bx = bx->prev())
bx->location.y = yy;
}
void
Box::move(Coord dx) //@# should be an LRBox member
{
Box* bx;
for(bx = this; bx; bx = bx->prev())
bx->location.x += dx;
}
void
Box::render(const BRect&)
{
if(formnode && bytes)
formnode->render(first_, bytes, location);
}
TextPosition
Box::position(const Extent& avail)
{
Extent used;
return first() + formnode->character_shape(first_, bytes,
avail, used, 0);
}
Coord
Box::locate(TextPosition here, Coord top, Coord bottom) const
{
here -= first();
assert(here<=bytes);
if(here>0){
Extent avail(location.x, location.x, location.x+width, top, bottom);
Extent used;
formnode->character_shape(first_, here,
avail, used, 0);
return location.x + used.width();
}else
return location.x;
}
LRBox::LRBox(LRBox* prev)
{
prev_ = prev;
runs = 0;
f = -1;
}
TextPosition
LRBox::position(Coord x)
{
Box* s;
Extent avail(0, 0, x, top(), bottom());
for(s = runs; s; s = s->prev())
if(x > s->left()){
avail.current_x(s->left());
return s->position(avail);
}
else if(s->prev() == 0){
return s->first();
}
}
Coord
LRBox::locate(TextPosition here) const
{
Box* s;
for(s = runs; s; s = s->prev())
if(here >= s->first()){
return s->locate(here, top(), bottom());
}
return 0;
}
TextPosition
LRBox::format(const TextFlow* flow, TextPosition first, TextPosition last,
Extent avail, Extent& total, int just)
{
Box* b = 0;
Extent used;
int word_wrap = 0;
Coord gap = 0;
total.y0 = total.y1 = 0;
delete runs;
f = first;
while(first < last){
b = new Box(b);
first = b->format(flow, first, last, avail, used, 1);
if(word_wrap == 0 && used.bad())
first = b->format(flow, first, last, avail, used, 0);
if(used.bad()){
b = b->destroy();
if(b == 0)
total.make_bad();
break;
}
if(used.x2>0) gap = used.x2;
word_wrap = 1;
total.max_ascent(used.ascent());
total.max_descent(used.descent());
b->x(avail.current_x(), used.width());
avail.move(used.width());
}
runs = b;
y0_ = avail.ascent();
ascent = total.ascent();
descent = total.descent();
/* justify boxes */
if(b){
b->y(avail.ascent() + total.ascent());
if(just == 1)
b->move(gap); //right just
else if(just == 2)
b->move(gap/2); //center just
}
return first;
}
void
LRBox::render(const BRect& bounds)
{
Box* r = runs;
while(r && r->left() > bounds.right())
r = r->prev();
while(r && r->right() > bounds.left()){
r->render(bounds);
r = r->prev();
}
}